/*******************************************************************************
* @file     usb task
* @version  V1.00
*******************************************************************************/
#include "bsp_api.h"
#include "ff_gen_drv.h"
#include "usbh_diskio.h"
#include "os_obj.h"
#include "nor_cmd.h"

/*****************************************************************************
* @brief   const 
*****************************************************************************/

/*****************************************************************************
* @brief   function
*****************************************************************************/
void MX_USB_HOST_Process(void);
uu8 usb_fat_scan_files(char *path);

/*****************************************************************************
* @brief   extern var
*****************************************************************************/
extern USBH_HandleTypeDef hUSB_Host;

/*****************************************************************************
* @brief   loacal var
*****************************************************************************/
uu16 usb_dev_found_time;
TCHAR usb_path[] = {'1', ':', 0}; /* SD drive started from 0 */

struct sdfat_str
{
	FIL fil;
	FRESULT fst;
	DIR dir;
	FATFS fat;
	FILINFO finfo;
	uu8 *buff;
	UINT len_back;
} usbf;

/*****************************************************************************
* @brief   sd_task.
* @param   argument
* @return  none
*****************************************************************************/
void usb_task(void *argument)
{
	osDelay(ms_ticks(1000));

	while (1)
	{
		osDelay(ms_ticks(4));
		MX_USB_HOST_Process();
		if (USBH_MSC_UnitIsReady(&hUSB_Host, 0))
		{
			if (usb_dev_found_time < UINT16_MAX)
			{
				usb_dev_found_time++;
			}

			if (usb_dev_found_time == 200)
			{
				// 申请缓存
				usbf.buff = malloc(0x1000 + 16);

				file_dbg_puts("usb msc insert, read file list in root :\n");

				f_mount(&usbf.fat, usb_path, 1);

				// path
				usbf.fst = f_chdrive(usb_path);

				if (usbf.fst == FR_OK)
				{
					usb_fat_scan_files("/");
				}
				else
				{
					file_dbg_puts("ch diver fail \n");
				}
				
				// copy font file to flash
				usbf.fst = f_open(&usbf.fil, "YaHei_24.BIN", FA_READ);
				if((usbf.fst == FR_OK) && (usbf.fil.obj.objsize < 0x100000) )
				{
					uu32 addr = 0;
					file_dbg_puts("found file \"YaHei_24.BIN\", copy it to nor flash @ 0x00000000\n");
					do
					{
						usbf.fst = f_read(&usbf.fil,usbf.buff, 0x1000, &usbf.len_back);
						nor_sector_erase(addr);
						nor_write_multi(addr, usbf.len_back, usbf.buff);
						addr += usbf.len_back;
					} while((usbf.len_back == 0x1000) && (usbf.fst == FR_OK) && (addr < 0x100000));

					file_dbg_print("copy file \"YaHei_24.BIN\" to nor flash size: 0x%X\n", addr);
				}
				
				f_close(&usbf.fil);

				// copy img file to flash
				usbf.fst = f_open(&usbf.fil, "zmfiles.zip", FA_READ);
				if((usbf.fst == FR_OK) && (usbf.fil.obj.objsize < 0x200000) )
				{
					uu32 addr_offset = 0;

					file_dbg_puts("found file \"zmfiles.zip\", copy it to nor flash @ 0x100000\n");
					do
					{
						usbf.fst = f_read(&usbf.fil,usbf.buff, 0x1000, &usbf.len_back);
						nor_sector_erase(addr_offset + 0x100000);
						nor_write_multi(addr_offset + 0x100000, usbf.len_back, usbf.buff);
						addr_offset += usbf.len_back;
					} while((usbf.len_back == 0x1000) && (usbf.fst == FR_OK) && (addr_offset < 0x200000));

					file_dbg_print("copy file \"zmfiles.zip\" to nor flash size: 0x%X\n", addr_offset);
				}
				
				f_close(&usbf.fil);
				
				f_mount(0, "0:", 1);
			}
		}
		else
		{
			usb_dev_found_time = 0;
		}

		// 释放缓存
		if(usbf.buff)
		{
			free(usbf.buff);
			usbf.buff = 0;
		}
	}
}

/*****************************************************************************
* @brief   mf_scan_files
* @param   path
* @return  none
* @ Pass/ Fail criteria: none
*****************************************************************************/
uu8 usb_fat_scan_files(char *path)
{
	FRESULT res;
	char *fn; /* This function is assuming non-Unicode cfg. */
	int16_t site, pdf_cnt = 0;

#if _USE_LFN
	//fileinfo.lfsize = _MAX_LFN * 2 + 1;
	//fileinfo.lfname = malloc(fileinfo.lfsize);
#endif

	res = f_opendir(&usbf.dir, (const char *)path);

	if (res == FR_OK)
	{
		while (1)
		{
			res = f_readdir(&usbf.dir, &usbf.finfo);

			if (res != FR_OK || usbf.finfo.fname[0] == 0)
				break;

#if _USE_LFN
			//fn = *fileinfo.lfname ? fileinfo.lfname : fileinfo.fname;
			fn = usbf.finfo.fname;
#else
			fn = usbf.finfo.fname;
#endif /* It is a file. */
			if (usbf.finfo.fattrib & AM_DIR)
			{
				file_dbg_print("fonund usbf.dir %s \n", fn);
			}
			else
			{
				file_dbg_print("fonund file %s \n", fn);
				site = str_nsearch_ch(fn, '.');

				if (site > 0)
				{
					if (0 == comp_string((void *)&fn[site], (void *)".PDF\0", 5))
					{
						pdf_cnt++;
					}
				}
			}
		}

		file_dbg_print("fonund pdf file amount : %d \n", pdf_cnt);
	}
	else
	{
		file_dbg_puts("open usbf.dir fail !\n");
	}

	return res;
}
